package com.restkeeper.controller;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.restkeeper.dto.*;
import com.restkeeper.model.wx.SendMessageDto;
import com.restkeeper.service.CommonService;
import com.restkeeper.service.WeChatSendService;
import com.restkeeper.service.WeChatService;
import com.restkeeper.utils.Result;
import com.restkeeper.utils.ResultCode;
import com.restkeeper.utils.Snowflake;
import com.restkeeper.utils.device.SignatureUtil;
import com.wechat.pay.java.service.refund.model.Refund;
import com.wechat.pay.java.service.transferbatch.model.InitiateBatchTransferResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.*;


import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.util.Map;

@Slf4j
@RequestMapping("/weChat")
@RestController
@RequiredArgsConstructor
public class WeChatController {

    private final WeChatService weChatService;
    private final WeChatSendService weChatSendService;
    private final CommonService commonService;

    /**
     * 登录
     * */
    @PostMapping("/login")
    public Result login(@RequestBody AppLoginDto dto){
        return weChatService.login(dto);
    }

    /**
     * 发送模板消息
     */
    @PostMapping(value = "/send_wx_msg")
    public void senMsg(@RequestBody SendMessageDto dto){
        switch (dto.getSendKey()){
            case "binding_success": weChatSendService.sendWxMsg(weChatSendService.bindingSuccess(dto));
            case "police": weChatSendService.police(dto);
//            default:return Result.error(ResultCode.message_type_null,"未匹配到消息类型");
        }
    }


    /**
     * 测试退款
     * */
    @PostMapping("/testRefund")
    public Result testRefund(@RequestBody WechatRefundDto dto) {
        Snowflake snowflake = new Snowflake(1, 1);
        Long l = snowflake.nextId();
        dto.setOutRefundNo(l.toString());
        log.info("退款param：【{}】", dto);
        Refund refund = commonService.wechatRefund(dto);
        log.info("Refund：【{}】", refund);
        if("PROCESSING".equals(refund.getStatus())){
            log.info("PROCESSING：退款处理中。。。");
        }
        return Result.ok(refund);
    }




    /**
     * 验证消息是否来自微信服务器
     *
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/confirmFromWx", method = {RequestMethod.GET, RequestMethod.POST})
    public void confirmFromWx(HttpServletRequest request, HttpServletResponse response) throws Exception {
        log.info("****************来自微信服务器的请求:{}", request.getMethod().toUpperCase());
        //微信服务器POST请求时,用的是UTF-8编码,在接收时也要用同样的编码,否则中文乱码
        request.setCharacterEncoding("UTF-8");
        //响应消息时,也要设置同样的编码
        response.setCharacterEncoding("UTF-8");
        //判断请求方式是否是post
        boolean isPost = Objects.equals("POST", request.getMethod().toUpperCase());
        if (isPost) {
            log.info("从微信服务器发过来POST请求,准备处理......");
//            {ScanType=qrcode, ScanResult=867896071145257,
//            ScanCodeInfo=CreateTime=1730449836, EventKey=scancode-02, Event=scancode_waitmsg, ToUserName=gh_7f517ea75b16, FromUserName=o2Uz_6RtbZ7kz9CFh8IyIk91DzNg, MsgType=event}
            Map<String, String> stringStringMap = xmlToMap(request);
            //菜单key
            String eventKey = stringStringMap.get("EventKey");
            log.info("==================EventKey============={}",eventKey);
            //事件类型
            String scanType = stringStringMap.get("ScanType");
            //处理扫码事件
            if("xjd-scancode-01".equals(eventKey)){
                log.info("****************stringStringMap:{}", stringStringMap);
                log.info("****************isPost:{}", isPost);
                PrintWriter out = null;
                try {
                    String respMessage = weChatService.callback(stringStringMap);
                    if (StringUtils.isBlank(respMessage)) {
                        log.info("不回复消息");
                        return;
                    }
                    log.info("------------------------------------------------------");
                    log.info("回复消息:{}", respMessage);
                    response.setCharacterEncoding("UTF-8");
                    out = response.getWriter();
                    out.write(respMessage);
                } catch (Throwable e) {
                    log.error("微信发送消息失败", e);
                } finally {
                    if (out != null) {
                        out.close();
                    }
                }
            }
            log.info("从微信服务器发过来POST请求,处理结束......");
        } else {
            log.info("********************验证微信服务器信息开始********************");
            //微信加密签名，signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
            String signature = request.getParameter("signature");
            //时间戳
            String timestamp = request.getParameter("timestamp");
            //随机数
            String nonce = request.getParameter("nonce");
            //随机字符串
            String echostr = request.getParameter("echostr");
            if (StringUtils.isEmpty(signature) || StringUtils.isEmpty(timestamp) || StringUtils.isEmpty(nonce) || StringUtils.isEmpty(echostr)) {
                return;
            }
            log.info("weChat: signature is: " + signature + ",timestamp is: " + timestamp + ",nonce is:" + nonce + ",echostr is:" + echostr);
            String check = weChatService.checkSignature(signature, timestamp, nonce, echostr);
            if (StringUtils.isNotBlank(check)) {
                log.info("********************校验成功,确实来自微信服务器,验证结束********************");
                response.getWriter().write(check);
            }
            log.info("********************验证微信服务器信息结束********************");
            response.getWriter().write("");
        }
    }

    /**
     * 获取微信 JS-SDK 配置信息
     *
     * @param url 当前页面的 URL，不包含 # 及其后面部分
     * @return 包含微信 JS-SDK 配置信息的结果
     */
    @GetMapping("/getJsSdkConfig")
    public Result getJsSdkConfig(@RequestParam String url) {
        try {
            log.info("getJsSdkConfig:[{}]",url);
            // 调用服务层方法获取 JS-SDK 签名信息
            Map<String, String> jsSdkConfig = weChatService.getJsSdkConfig(url);
            log.info("jsSdkConfig:[{}]",jsSdkConfig);
            return Result.ok(jsSdkConfig);
        } catch (Exception e) {
            log.error("获取微信 JS-SDK 配置信息失败", e);
            return Result.error(ResultCode.error, "获取微信 JS-SDK 配置信息失败");
        }
    }



    public static Map<String,String> xmlToMap(HttpServletRequest request){
        Map<String, String> map = new HashMap<String,String>();
        SAXReader reader = new SAXReader();
        try {
            //从request中获取输入流
            InputStream inputStream = request.getInputStream();
            Document document = reader.read(inputStream);
            //获取xml的根节点
            Element root = document.getRootElement();
            //获取根元素的所有子节点
            List<Element> list = root.elements();
            //遍历list
            for(Element element:list){
                //遍历的结果放到集合中
                map.put(element.getName(), element.getText());
                List<Element> elementsSon = element.elements();
                for(Element elementSon:elementsSon){
                    //遍历的结果放到集合中
                    map.put(elementSon.getName(), elementSon.getText());
                }
            }
            //关闭流
            inputStream.close();

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {

        }
        //返回map集合
        return map;
    }

    /**
     * 获取请求来源ip地址
     * */
    public String getIpAddress(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }


}
